package com.linwen.javase.string;

import org.junit.Test;

/**
 * @author lin
 * @date 2020年2月18日
 * @version 1.0 
 */
/*
 * 1:String类被final修饰，String类不能再被继承，也即对String 的操作方法，不会再被继承重写；
 * 2:String的底层实现是通过char类型的字符数组value而实现，value同时也被final修饰，也即在赋值后无法修改；
 * 且访问权限是private，外部无法访问，而String本身也无修改的方法，所以value赋值后，内存地址无法修改；
 *!!! 因为String 的不变性所以String 的大多数操作方法都会返回新的String
 * StringBuilder是线程不安全的，StringBuffer是线程安全的，所以比较耗时的
 * */
@SuppressWarnings("all")
public class MyString {

	//String+  和 StringBuilder的append方法效率比较
	//String+底层也是StringBuilder
	//+是java的一种语法糖的写法，其底层的字符串拼接还是StringBuilder的append。
	@Test
	public void test1(){
		long startTime = System.currentTimeMillis();
		String string = "";
		for(int i=0;i<100000;i++) {
			string += "1";
		}
		long endTime = System.currentTimeMillis();
		System.out.println(endTime-startTime+"ms");


		long startTime1 = System.currentTimeMillis();
		StringBuilder stringBuilder = new StringBuilder();
		for(int i=0;i<100000;i++) {
			stringBuilder.append("1");
		}
		long endTime1 = System.currentTimeMillis();
		System.out.println(endTime1-startTime1+"ms");

		long startTime2 = System.currentTimeMillis();
		StringBuffer stringBuffer = new StringBuffer();
		for(int i=0;i<100000;i++) {
			stringBuffer.append("1");
		}
		long endTime2 = System.currentTimeMillis();
		System.out.println(endTime2-startTime2+"ms");
	}

	//StringBuilder是否指定容量性能区别
	//指定容量比不指定容量快
	@Test
	public void test2() {
		long startTime = System.currentTimeMillis();
		StringBuilder stringBuilder = new StringBuilder(10000);
		for(int i=0;i<10000000;i++) {
			stringBuilder.append("test");
		}
		long endTime = System.currentTimeMillis();
		System.out.println(endTime-startTime+"ms");


		long startTime1 = System.currentTimeMillis();
		StringBuilder stringBuilder2 = new StringBuilder();
		for(int i=0;i<10000000;i++) {
			stringBuilder2.append("hello");
		}
		long endTime1 = System.currentTimeMillis();
		System.out.println(endTime1-startTime1+"ms");
	}

	@Test
	public void test3() throws InterruptedException {
		// 验证stringBuffer是线程安全的，StringBuilder是线程不安全的
		StringBufferThread stringBufferThread = new StringBufferThread();
		StringBuilderThread stringBuilderThread = new StringBuilderThread();
		new Thread(stringBufferThread).start();
		new Thread(stringBufferThread).start();
		new Thread(stringBufferThread).start();

		new Thread(stringBuilderThread).start();
		new Thread(stringBuilderThread).start();
		new Thread(stringBuilderThread).start();
		// 保证主线程没有结束，否则主线程执行完不保证其他线程执行完。
		Thread.sleep(5000);
		System.out.println(stringBufferThread.stringBufferToString());
		System.out.println(stringBufferThread.stringBuffer.length());
		System.out.println(stringBuilderThread.stringBuilderToString());
		System.out.println(stringBuilderThread.stringBuilder.length());
	}

	@Test
	public void test4() {

		String str1 = "abc";
		// 获取指定位置的字符编码
		System.out.println(str1.codePointAt(2));
		// 将字符串作为流返回
		System.out.println(str1.codePoints().count());


	}

}
